package com.small.sentinel.slots.statistic.data;

import com.small.sentinel.slots.statistic.MetricEvent;

import java.util.concurrent.atomic.LongAdder;

public class MetricBucket {

    private final LongAdder[] counters;

    /**
     * 最小完成时长
     */
    private volatile long minRt;

    public MetricBucket() {
        MetricEvent[] events = MetricEvent.values();
        this.counters = new LongAdder[events.length];
        for (MetricEvent event : events) {
            counters[event.ordinal()] = new LongAdder();
        }
        initMinRt();
    }

    /**
     * 重置当前窗口的值,将传进来的窗口值复制到当前窗口
     * @param bucket
     * @return
     */
    public MetricBucket reset(MetricBucket bucket) {
        for (MetricEvent event : MetricEvent.values()) {
            counters[event.ordinal()].reset();
            counters[event.ordinal()].add(bucket.get(event));
        }
        initMinRt();
        return this;
    }

    /**
     * 重置当前窗口所有的值
     * @return
     */
    public MetricBucket reset() {
        for (MetricEvent event : MetricEvent.values()) {
            counters[event.ordinal()].reset();
        }
        return this;
    }


    public long pass() {
        return get(MetricEvent.PASS);
    }

    /**
     * 添加通过事件
     * @param n
     */
    public void addPass(int n) {
        add(MetricEvent.PASS, n);
    }

    /**
     * 添加完成事件
     * @param n
     */
    public void addSuccess(int n) {
        add(MetricEvent.SUCCESS, n);
    }

    /**
     * 添加对应事件的值
     * @param event
     * @param n
     * @return
     */
    public MetricBucket add(MetricEvent event, long n) {
        counters[event.ordinal()].add(n);
        return this;
    }

    public void addRT(long rt) {
        add(MetricEvent.RT, rt);

        if (rt < minRt) {
            minRt = rt;
        }
    }

    public void addException(int n) {
        add(MetricEvent.EXCEPTION, n);
    }

    public void addBlock(int n) {
        add(MetricEvent.BLOCK, n);
    }

    /**
     * 获取对应时间的值
     * @param event
     * @return
     */
    public long get(MetricEvent event) {
        return counters[event.ordinal()].sum();
    }


    private void initMinRt() {
        this.minRt = 5000L;
    }
}
